/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkRtpTcpClient.h"
#include "MkUtil/MkLog.h"
#include "MkRtpUtil.h"

CMkRtpTcpClient::CMkRtpTcpClient(CMkEvent* pEvent, CMkTimer* pTimer, const MkEventRemovedCallback& RemovedCb)
    : CMkTcpClient(pEvent, pTimer, RemovedCb)
    , CMkRtp(pTimer)  //rtp over tcp not check rtcp
    , m_nOffset(0)
    , m_nMaxLen(Len2K)
{
    m_pRecvBuffer = (Uint8*)malloc(m_nMaxLen);
}

Uint32 CMkRtpTcpClient::Start(const Uint16& TcpPort)
{
    Uint32 ErrorCode = Create(FALSE);
    MkCheckErrorLog(ErrorCode, "create failed\n");

    return Bind(TcpPort);
}

Uint32 CMkRtpTcpClient::DeleteRemoter(const Uint32& Ssrc)
{
    if (NoneError == CMkRtp::DeleteRemoter(Ssrc)) {
        Close();
    }
    return NoneError;
}

Uint32 CMkRtpTcpClient::SendRtpPacket(const CMkRtpPacket& RtpPacket, const MkString& RemoteIp, Uint16 RemotePort)
{
    MkUnUse(RemotePort);
    MkUnUse(RemoteIp);
    CMkBufferList BufList;
    Uint16 nLen = RtpPacket.GetHeaderLen() + RtpPacket.GetPayloadLength();
    nLen = ntohs(nLen);
    BufList.Append(&nLen, sizeof(Uint16));
    BufList.Append(RtpPacket.GetHeaderData(), RtpPacket.GetHeaderLen());
    if (RtpPacket.GetPayloadData()) {
        BufList.Append(RtpPacket.GetPayloadData(), RtpPacket.GetPayloadLength());
    } else {
        BufList.Append(RtpPacket.GetPayloadBufferList());
    }
    MkInfoLog("rtp client send rtp packet to (%s:%d)\n", GetRemoteHost().c_str(), GetRemotePort());
    return Send(BufList);
}

Uint32 CMkRtpTcpClient::SendRtcpPacket(const CMkRtcpPacket& RtcpPacket, const MkString& RemoteIp, Uint16 RemotePort)
{
    MkUnUse(RemotePort);
    MkUnUse(RemoteIp);
    Uint8 pBuf[Len1K] = { 0 };
    Uint32 nUsed = 0;
    RtcpPacket.Packet(pBuf, Len1K, nUsed);
    Uint16 nLen = nUsed;
    nLen = ntohs(nLen);
    CMkBufferList BufList;
    BufList.Append(&nLen, sizeof(Uint16));
    BufList.Append(pBuf, nUsed);
    MkInfoLog("rtp client send rtcp packet to (%s:%d)\n", GetRemoteHost().c_str(), GetRemotePort());
    return Send(BufList);
}

Uint32 CMkRtpTcpClient::Release()
{
    Close();
    return NoneError;
}

Uint32 CMkRtpTcpClient::OnRecv()
{
    Uint32 nToRead = m_nMaxLen - m_nOffset;
    if (0 == nToRead) {
        MkWarningLog("recv max rtp len not parse rtp packet\n");
        MkRtpRemoter Remoter;
        if (NoneError == GetFirstRemoter(Remoter) && Remoter.RtpClosedCb) {
            Remoter.RtpClosedCb();
        }
        return NoneError;
    }
    Uint32 ErrorCode = Recv(m_pRecvBuffer + m_nOffset, nToRead);
    MkCheckErrorLog(ErrorCode, "rtp tcp client recv error\n");
    MkInfoLog("rtp client recv packet to (%s:%d)\n", GetRemoteHost().c_str(), GetRemotePort());
    m_nOffset += nToRead;
    Uint32 nUsed = 0;
    Uint16 PacketLen = 0;
    while (nUsed + 2 < m_nOffset) {
        PacketLen = (m_pRecvBuffer[nUsed] << 8) | (m_pRecvBuffer[nUsed + 1]);
        if (nUsed + 2 + PacketLen > m_nOffset) {
            break;
        }
        nUsed += 2;
        ParsePacket(m_pRecvBuffer + nUsed, PacketLen);
        nUsed += PacketLen;
    }
    memmove(m_pRecvBuffer, m_pRecvBuffer + nUsed, m_nOffset - nUsed);
    m_nOffset -= nUsed;
    return NoneError;
}

Uint32 CMkRtpTcpClient::ParsePacket(Uint8* pBuf, Uint32 nLen)
{
    Uint32 ErrorCode = NoneError;
    CMkRtpPacket RtpPacket;
    CMkRtcpPacket RtcpPacket;
    if (NoneError == RtpPacket.Parse(pBuf, nLen)) {
        ParseRtpPacket(RtpPacket, GetRemoteHost(), GetRemotePort());
    } else {
        Uint32 nUsed = 0;
        Uint32 nCurUsed = 0;
        while (nUsed < nLen) {
            ErrorCode = RtcpPacket.Parse(pBuf + nUsed, nLen - nUsed, nCurUsed);
            if (NoneError != ErrorCode) {
                break;
            }
            ParseRtcpPacket(RtcpPacket, GetRemoteHost(), GetRemotePort());
            nUsed += nCurUsed;
        }
    }
    return NoneError;
}

Uint32 CMkRtpTcpClient::OnEventRemoved()
{
    CMkRtp::DeleteRemoter(MaxInt32);
    return CMkTcpClient::OnEventRemoved();
}

Uint32 CMkRtpTcpClient::OnConnect()
{
    CMkTcpClient::OnConnect();
    //send rtcp describe
    MkRtpRemoter Remoter;
    Uint32 ErrorCode = GetFirstRemoter(Remoter);
    if (NoneError != ErrorCode) {
        return NoneError;
    }
    Uint8 pRtpBuf[Len1K] = { 0 };
    Uint32 nUsed = 0;
    if (MkRtpSender & Remoter.RtpType) {
        CMkRtcpPacket SenderReportRtcp;
        SenderReportRtcp.SetPayload(MkRtcpSr);
        SenderReportRtcp.SetSenderReportSsrc(Remoter.Ssrc);
        SenderReportRtcp.SetSenderReportNtpTimeStamp(NowMkTime.GetTvSec());
        SenderReportRtcp.SetSenderReportRtpTimeStamp(Remoter.TimeStamp);
        SenderReportRtcp.SetSenderReportSenderPacketCount(Remoter.SendPacketCount);
        SenderReportRtcp.SetSenderReportSenderOctetCount(0);
        SendRtcpPacket(SenderReportRtcp, Remoter.RtpRemoteHost, Remoter.RtpRemotePort);
    }
    if (MkRtpRecver & Remoter.RtpType) {
        CMkRtcpPacket RecverReportRtcp;
        RecverReportRtcp.SetPayload(MkRtcpRr);
        RecverReportRtcp.SetReceptionSsrc(Remoter.Ssrc);
        SendRtcpPacket(RecverReportRtcp, Remoter.RtpRemoteHost, Remoter.RtpRemotePort);
    }

    CMkRtcpPacket DescRtcp;
    DescRtcp.SetPayload(MkRtcpSdes);
    DescRtcp.SetSourceDescriptionSsrc(Remoter.Ssrc);
    DescRtcp.SetSourceDescriptionAddChunk(MkSdesName, "MkRtp");
    SendRtcpPacket(DescRtcp, Remoter.RtpRemoteHost, Remoter.RtpRemotePort);
    return NoneError;
}

CMkRtpTcpClient::~CMkRtpTcpClient()
{
    MkFree(m_pRecvBuffer);
}